home *** CD-ROM | disk | FTP | other *** search
-
- #import "QueensController.h"
-
- @implementation QueensController
-
- // set up board
- // use selected buttons for white squares
- - awakeFromNib
- {
- int i, j;
-
- for (i=0; i LT 8; i++)
- for ( j=0; j LT 8; j++)
- {
- id cell = [board cellAt: i : j];
-
- [cell setEnabled: NO];
- if ( (i+j)%1 )
- [board selectCell: cell];
- }
-
- rows = 0; // only 1 row valid
- column[0] = 0; // only search last 4 due to symmetry
- [self placeQueenAt: 0 : column[0]];
- [board display];
- return( self);
- }
-
-
- /* Action messages */
-
- - motor:sender
- {
- running = YES;
- [self motorStep];
- return( self);
- }
-
-
- - pause: sender
- {
- running = NO;
- return( self);
- }
-
-
- - step: sender
- {
- running = [self countStep];
- return( self);
- }
-
-
- // place another queen
- - (BOOL)countStep
- {
- BOOL placed = [self stepFrom: 0];
-
- // update counter
- [stepsDisplay setIntValue: [stepsDisplay intValue]+1];
-
- // if placed on row 7, it is solved
- // update solutions and maybe pause
- if ( rows EQ 7 )
- {
- [solutionsDisplay setIntValue: [solutionsDisplay intValue]+1];
- if ( [solutionPause intValue] )
- return( NO);
- }
-
- return( placed);
- }
-
-
- - motorStep
- {
- // iterate single steps,
- // but delay between steps to allow
- // pause message
- if ( running )
- {
- running = [self countStep];
-
- [self perform:
- @selector( motorStep) with: nil
- afterDelay: 20 cancelPrevious: YES
- ];
- }
-
- return( self);
- }
-
-
- // set the queen icon for the chosen cell
- - placeQueenAt: (int)aRow : (int)aColumn
- {
- id cell = [board cellAt: aRow : aColumn];
- NXRect cellFrame;
-
- [cell setIcon: "queen"];
- [board getCellFrame: &cellFrame at: aRow : aColumn];
- [board display: &cellFrame : 1];
- return( self);
- }
-
-
- // go back to no icon for the cell
- - removeQueenFrom: (int)aRow : (int)aColumn
- {
- id cell = [board cellAt: aRow : aColumn];
- NXRect cellFrame;
-
- [cell setIcon: ""];
- [board getCellFrame: &cellFrame at: aRow : aColumn];
- [board display: &cellFrame : 1];
- return( self);
- }
-
-
- // recursive scan
- - (BOOL)stepFrom: (int)aRow
- {
- int i;
- //limit recursion to 8 rows
- if ( aRow LT 8 )
- {
- // if not at end of placed rows
- // go immediately to next row
- if ( aRow LE rows )
- {
- if ( [self stepFrom: aRow+1] )
- return( YES);
-
- // if at empty row, fall through
- // to continue scan
- else
- {
- rows = aRow;
- [self removeQueenFrom: aRow : column[ aRow]];
- column[ aRow] += 1;
- }
- }
-
- // scan remainder of this row
- for ( i=column[ aRow]; i LT 8; i++ )
- {
- // try next queen
- // if no attacks, move to next row
- [self placeQueenAt: aRow : i];
- if ( [self validate: aRow : i] )
- {
- column[ aRow] = i;
- rows = aRow;
- return( YES);
- }
-
- // remove this queen and continue
- [self removeQueenFrom: aRow: i];
- }
-
- // reset this column and back up
- column[ aRow] = 0;
- }
-
- return( NO);
- }
-
-
- // check for attacks...
- // another queen in same column
- // or on diagonal
- - (BOOL)validate: (int)aRow : (int) aColumn
- {
- int i;
-
- for ( i=0; i LT aRow; i++ )
- {
- int rowDistance = aRow - i;
- int columnDistance = aColumn - column[i];
-
- if (
- aColumn EQ column[i]
- || rowDistance EQ columnDistance
- || rowDistance EQ -columnDistance
- )
- return( NO);
- }
-
- return( YES);
- }
-
-
- @end
-